#include <fcntl.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "Mensajes.h"

using namespace std;  

const char escribir_shm[] = "/_escribir_shm";
const char leer_shm[]= "/_leer_shm";
sem_t* mutex_escribir_shm;
sem_t* mutex_leer_shm;

int id_mem = 0;
EstadoPartida *mcompartida = NULL;

void CrearMemoriaCompartida()
{
	if((mutex_escribir_shm = sem_open(escribir_shm, O_CREAT | O_EXCL ,0666, 1)) == SEM_FAILED)
		error("No se puede abrir el semáforo\n");

	if((mutex_leer_shm = sem_open(leer_shm, O_CREAT | O_EXCL ,0666, 0)) == SEM_FAILED)
		error("No se puede abrir el semáforo\n");

	// Generar clave
	key_t sh_key = ftok("/bin/ls",10);
	
	if(sh_key == -1)
		error("No consigo clave para memoria compartida\n");

	// Generar memoria compartida
	id_mem = shmget(sh_key,sizeof(EstadoPartida),0777 | IPC_CREAT);
	
	if (id_mem == -1)
		error("No consigo Id para memoria compartida\n");

	// Attach memoria
	mcompartida = (EstadoPartida *)shmat(id_mem,NULL,0);
	if(mcompartida == NULL)
		error("No hay memoria compartida disponible\n");
}

void LiberarMemoriaCompartida()// Liberar memoria
{
	cout << getpid() << ">> Eliminamos memoria" << endl;
	if(mutex_escribir_shm)
	{
		sem_close(mutex_escribir_shm);
		sem_unlink(escribir_shm);
	}

	if(mutex_leer_shm)
	{
		sem_close(mutex_leer_shm);
		sem_unlink(leer_shm);
	}

	shmdt(mcompartida);
	shmctl(id_mem, IPC_RMID,(struct shmid_ds *)NULL);
}

void EscribirMemoriaCompartida(EstadoPartida aux)
{
	P(mutex_escribir_shm);
	*mcompartida = aux;
	V(mutex_leer_shm);
}

EstadoPartida LeerMemoriaCompartida()
{
	EstadoPartida aux; 

	P(mutex_leer_shm);
	aux = *mcompartida;
	V(mutex_escribir_shm);

	return aux;
}

///////// Semáforos /////////

void P(sem_t* sem)
{
	if(sem_wait(sem) == -1)
		error("Semáforo no válido");
}

void V(sem_t* sem)
{
	if(sem_post(sem) == -1)
		error("Semáforo no válido");
}
